/*
 *------------------------------------------------------------------------------
 * @File      :    gc4663_mipi.c
 * @Date      :    2021-4-14
 * @Author    :    lomboswer <lomboswer@lombotech.com>
 * @Brief     :    Source file for MDP(Media Development Platform).
 *
 * Copyright (C) 2020-2021, LomboTech Co.Ltd. All rights reserved.
 *------------------------------------------------------------------------------
 */
#include "ei_comm_camera.h"
#include "camera_usr.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#define SNS_ID 4663
#define SNS_NAME  "gc4663_mipi"
#define DEV_TYPE MCSI
static VISS_DEV gaVissDev[ISP_MAX_DEV_NUM] = {-1};
static SNS_STATE_S g_sastSns[VISS_MAX_DEV_NUM];


static const SNS_REG_S s_aRaw10b1920x108030fps2Lane[] = {
    //version 6.8
    //mclk 24Mhz
    //mipi_data_rate 648Mbps
    //framelength 1500
    //linelength 4800
    //pclk 216Mhz
    //rowtime 22.2222us
    //pattern grbg
    {0x03fe,0xf0},
    {0x03fe,0x00},
    {0x0317,0x00},
    {0x0320,0x77},
    {0x0324,0xc8},
    {0x0325,0x06},
    {0x0326,0x6c},
    {0x0327,0x03},
    {0x0334,0x40},
    {0x0336,0x6c},
    {0x0337,0x82},
    {0x0315,0x25},
    {0x031c,0xc6},
    {0x0287,0x18},
    {0x0084,0x00},
    {0x0087,0x50},
    {0x029d,0x08},
    {0x0290,0x00},
    {0x0340,0x05},
    {0x0341,0xdc},
    {0x0345,0x06},
    {0x034b,0xb0},
    {0x0352,0x08},
    {0x0354,0x08},
    {0x02d1,0xe0},
    {0x0223,0xf2},
    {0x0238,0xa4},
    {0x02ce,0x7f},
    {0x0232,0xc4},
    {0x02d3,0x05},
    {0x0243,0x06},
    {0x02ee,0x30},
    {0x026f,0x70},
    {0x0257,0x09},
    {0x0211,0x02},
    {0x0219,0x09},
    {0x023f,0x2d},
    {0x0518,0x00},
    {0x0519,0x01},
    {0x0515,0x08},
    {0x02d9,0x3f},
    {0x02da,0x02},
    {0x02db,0xe8},
    {0x02e6,0x20},
    {0x021b,0x10},
    {0x0252,0x22},
    {0x024e,0x22},
    {0x02c4,0x01},
    {0x021d,0x17},
    {0x024a,0x01},
    {0x02ca,0x02},
    {0x0262,0x10},
    {0x029a,0x20},
    {0x021c,0x0e},
    {0x0298,0x03},
    {0x029c,0x00},
    {0x027e,0x14},
    {0x02c2,0x10},
    {0x0540,0x20},
    {0x0546,0x01},
    {0x0548,0x01},
    {0x0544,0x01},
    {0x0242,0x1b},
    {0x02c0,0x1b},
    {0x02c3,0x20},
    {0x02e4,0x10},
    {0x022e,0x00},
    {0x027b,0x3f},
    {0x0269,0x0f},
    {0x02d2,0x40},
    {0x027c,0x08},
    {0x023a,0x2e},
    {0x0245,0xce},
    {0x0530,0x20},
    {0x0531,0x02},
    {0x0228,0x50},
    {0x02ab,0x00},
    {0x0250,0x00},
    {0x0221,0x50},
    {0x02ac,0x00},
    {0x02a5,0x02},
    {0x0260,0x0b},
    {0x0216,0x04},
    {0x0299,0x1C},
    {0x02bb,0x0d},
    {0x02a3,0x02},
    {0x02a4,0x02},
    {0x021e,0x02},
    {0x024f,0x08},
    {0x028c,0x08},
    {0x0532,0x3f},
    {0x0533,0x02},
    {0x0277,0xc0},
    {0x0276,0xc0},
    {0x0239,0xc0},
    {0x0202,0x05},
    {0x0203,0xd0},
    {0x0205,0xc0},
    {0x02b0,0x68},
    {0x0002,0xa9},
    {0x0004,0x01},
    {0x021a,0x98},
    {0x0266,0xa0},
    {0x0020,0x01},
    {0x0021,0x03},
    {0x0022,0x00},
    {0x0023,0x04},
    {0x034c,0x07},
    {0x034d,0x80},
    {0x034e,0x04},
    {0x034f,0x38},

    {0x0352,0xb4},
    {0x0353,0x01},
    {0x0354,0x40},
    {0x0342,0x06},
    {0x0343,0x40},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0106,0x78},
    {0x0108,0x0c},
    {0x0114,0x01},
    {0x0115,0x12},
    {0x0180,0x46},
    {0x0181,0x30},
    {0x0182,0x05},
    {0x0185,0x01},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0100,0x09},//stream on
};

static const SNS_REG_S s_aRaw10b1920x108030fps2Lane2to1[] = {
    //version 4.2
    //mclk 24Mhz
    //mipiclk 1344Mbps
    //framelength 1600 ,vb=108
    //exp_L <= vb ,vb=frame_length-window_height-20-16
    //exp_H+exp_L<= framelength
    //if exp1 * 16 = exp2
    // exp1_max = 94, exp2_max = 1504
    //linelength
    //pclk
    //rowtime 10.41666667us
    //pattern grbg
    {0x03fe, 0xf0},
    {0x03fe, 0x00},
    {0x0317, 0x00},
    {0x0320, 0x77},
    {0x0324, 0xc4},
    {0x0326, 0x42},
    {0x0327, 0x03},
    {0x0321, 0x10},
    {0x0314, 0x50},
    {0x0334, 0x40},
    {0x0335, 0xd1},
    {0x0336, 0x70},
    {0x0337, 0x82},
    {0x0315, 0x33},
    {0x031c, 0xce},
    {0x0287, 0x18},
    {0x0084, 0x00},
    {0x0087, 0x50},
    {0x029d, 0x08},
    {0x0290, 0x00},
    {0x0340, 0x06},
    {0x0341, 0x40},
    {0x0345, 0x06},
    {0x034b, 0xb0},
    {0x0352, 0x08},
    {0x0354, 0x08},
    {0x02d1, 0xc0},
    {0x023c, 0x04},
    {0x0238, 0xb4},
    {0x0223, 0xfb},
    {0x0232, 0xc4},
    {0x0279, 0x53},
    {0x02d3, 0x01},
    {0x0243, 0x06},
    {0x02ce, 0xbf},
    {0x02ee, 0x30},
    {0x026f, 0x70},
    {0x0257, 0x09},
    {0x0211, 0x02},
    {0x0219, 0x09},
    {0x023f, 0x2d},
    {0x0518, 0x00},
    {0x0519, 0x14},
    {0x0515, 0x18},
    {0x02d9, 0x50},
    {0x02da, 0x02},
    {0x02db, 0xe8},
    {0x02e6, 0x20},
    {0x021b, 0x10},
    {0x0252, 0x22},
    {0x024e, 0x22},
    {0x02c4, 0x01},
    {0x021d, 0x17},
    {0x024a, 0x01},
    {0x02ca, 0x02},
    {0x0262, 0x10},
    {0x029a, 0x20},
    {0x021c, 0x0e},
    {0x0298, 0x03},
    {0x029c, 0x00},
    {0x027e, 0x14},
    {0x02c2, 0x10},
    {0x0540, 0x20},
    {0x0546, 0x01},
    {0x0548, 0x01},
    {0x0544, 0x01},
    {0x0242, 0x36},
    {0x02c0, 0x36},
    {0x02c3, 0x4d},
    {0x02e4, 0x10},
    {0x022e, 0x00},
    {0x027b, 0x3f},
    {0x0269, 0x0f},
    {0x02d2, 0x40},
    {0x027c, 0x08},
    {0x023a, 0x2e},
    {0x0245, 0xce},
    {0x0530, 0x3f},
    {0x0531, 0x02},
    {0x0228, 0x50},
    {0x02ab, 0x00},
    {0x0250, 0x00},
    {0x0221, 0x50},
    {0x02ac, 0x00},
    {0x02a5, 0x02},
    {0x0260, 0x0b},
    {0x0216, 0x04},
    {0x0299, 0x1C},
    {0x021a, 0x98},
    {0x0266, 0xd0},
    {0x0020, 0x01},
    {0x0021, 0x05},
    {0x0022, 0xc0},
    {0x0023, 0x08},
    //tony_add
    {0x0098, 0x10},
    {0x009a, 0xb0},
    {0x02bb, 0x0d},
    {0x02a3, 0x02},
    {0x02a4, 0x02},
    {0x021e, 0x02},
    {0x024f, 0x08},
    {0x028c, 0x08},
    {0x0532, 0x3f},
    {0x0533, 0x02},
    {0x0277, 0x70},//tx_width
    {0x0276, 0xc0},
    {0x0239, 0xc0},
    {0x0200, 0x00},
    {0x0201, 0x5f},
    {0x0202, 0x05},
    {0x0203, 0xf0},
    {0x0205, 0xc0},
    {0x02b0, 0x68},
    {0x000f, 0x00},
    {0x0006, 0xe0},
    {0x0002, 0xa9},
    {0x0004, 0x01},
    {0x0060, 0x40},
    {0x0218, 0x12},
    {0x034c, 0x07},
    {0x034d, 0x80},
    {0x034e, 0x04},
    {0x034f, 0x38},

    {0x0352, 0xb4},
    {0x0353, 0x01},
    {0x0354, 0x40},
    {0x0342, 0x05},
    {0x0343, 0x5f},
    {0x03fe, 0x10},
    {0x03fe, 0x00},
    {0x0106, 0x78},
    {0x0107, 0x89},
    {0x0108, 0x0c},
    {0x0114, 0x01},
    {0x0115, 0x12},
    /*modfied by tbl for increase prepare timing*/
    {0x0129, 0x10},

    {0x0180, 0x4f},
    {0x0181, 0x30},
    {0x0182, 0x05},
    {0x0185, 0x01},
    {0x03fe, 0x10},
    {0x03fe, 0x00},
    {0x0100, 0x09},
};

static const SNS_REG_S s_aRaw10b2560X144030fps2Lane2to1[] = {
    //version 4.2
    //mclk 24Mhz
    //mipiclk 1344Mbps
    //framelength 1600 ,vb=108
    //exp_L <= vb ,vb=frame_length-window_height-20-16
    //exp_H+exp_L<= framelength
    //if exp1 * 16 = exp2
    // exp1_max = 94, exp2_max = 1504
    //linelength
    //pclk
    //rowtime 10.41666667us
    //pattern grbg

    /* 20220805
     * Frame_Length(VTS) : 0x0340 0x0341 => 0x0640 => 1600
     * Vertical_Blanking(VB) : Frame_Length - Window_Height(0x034e, 0x034f) - 32 => 1600 - 1440 -32 => 128
     * Exp_Low < VB, Exp_Low + Exp_High < Frame_Length -8
     * Line_Length(HTS) : 0x033f 0x033e => 2750
     * Pclk : VTS x HTS x fps = 132000000
     * Pattern: RGrGbB
     * Rowtime: 1s / ((fps x 2) x VTS) = 10.41666667us
     */

    {0x03fe, 0xf0},
    {0x03fe, 0x00},
    {0x0317, 0x00},
    {0x0320, 0x77},
    {0x0324, 0xc4},
    {0x0326, 0x42},
    {0x0327, 0x03},
    {0x0321, 0x10},
    {0x0314, 0x50},
    {0x0334, 0x40},
    {0x0335, 0xd1},
    {0x0336, 0x70},
    {0x0337, 0x82},
    {0x0315, 0x33},
    {0x031c, 0xce},
    {0x0287, 0x18},
    {0x0084, 0x00},
    {0x0087, 0x50},
    {0x029d, 0x08},
    {0x0290, 0x00},
    {0x0340, 0x06},
    {0x0341, 0x40},
    {0x0345, 0x06},
    {0x034b, 0xb0},
    {0x0352, 0x08},
    {0x0354, 0x08},
    {0x02d1, 0xc0},
    {0x023c, 0x04},
    {0x0238, 0xb4},
    {0x0223, 0xfb},
    {0x0232, 0xc4},
    {0x0279, 0x53},
    {0x02d3, 0x01},
    {0x0243, 0x06},
    {0x02ce, 0xbf},
    {0x02ee, 0x30},
    {0x026f, 0x70},
    {0x0257, 0x09},
    {0x0211, 0x02},
    {0x0219, 0x09},
    {0x023f, 0x2d},
    {0x0518, 0x00},
    {0x0519, 0x14},
    {0x0515, 0x18},
    {0x02d9, 0x50},
    {0x02da, 0x02},
    {0x02db, 0xe8},
    {0x02e6, 0x20},
    {0x021b, 0x10},
    {0x0252, 0x22},
    {0x024e, 0x22},
    {0x02c4, 0x01},
    {0x021d, 0x17},
    {0x024a, 0x01},
    {0x02ca, 0x02},
    {0x0262, 0x10},
    {0x029a, 0x20},
    {0x021c, 0x0e},
    {0x0298, 0x03},
    {0x029c, 0x00},
    {0x027e, 0x14},
    {0x02c2, 0x10},
    {0x0540, 0x20},
    {0x0546, 0x01},
    {0x0548, 0x01},
    {0x0544, 0x01},
    {0x0242, 0x36},
    {0x02c0, 0x36},
    {0x02c3, 0x4d},
    {0x02e4, 0x10},
    {0x022e, 0x00},
    {0x027b, 0x3f},
    {0x0269, 0x0f},
    {0x02d2, 0x40},
    {0x027c, 0x08},
    {0x023a, 0x2e},
    {0x0245, 0xce},
    {0x0530, 0x3f},
    {0x0531, 0x02},
    {0x0228, 0x50},
    {0x02ab, 0x00},
    {0x0250, 0x00},
    {0x0221, 0x50},
    {0x02ac, 0x00},
    {0x02a5, 0x02},
    {0x0260, 0x0b},
    {0x0216, 0x04},
    {0x0299, 0x1C},
    {0x021a, 0x98},
    {0x0266, 0xd0},
    {0x0020, 0x01},
    {0x0021, 0x05},
    {0x0022, 0xc0},
    {0x0023, 0x08},
    //tony_add
    {0x0098, 0x10},
    {0x009a, 0xb0},
    {0x02bb, 0x0d},
    {0x02a3, 0x02},
    {0x02a4, 0x02},
    {0x021e, 0x02},
    {0x024f, 0x08},
    {0x028c, 0x08},
    {0x0532, 0x3f},
    {0x0533, 0x02},
    {0x0277, 0x70},//tx_width
    {0x0276, 0xc0},
    {0x0239, 0xc0},
    {0x0200, 0x00},
    {0x0201, 0x5f},
    {0x0202, 0x05},
    {0x0203, 0xf0},
    {0x0205, 0xc0},
    {0x02b0, 0x68},
    {0x000f, 0x00},
    {0x0006, 0xe0},
    {0x0002, 0xa9},
    {0x0004, 0x01},
    {0x0060, 0x40},
    {0x0218, 0x12},
    {0x0342, 0x05},
    {0x0343, 0x5f},
    {0x03fe, 0x10},
    {0x03fe, 0x00},
    {0x0106, 0x78},
    {0x0107, 0x89},
    {0x0108, 0x0c},
    {0x0114, 0x01},
    {0x0115, 0x12},
    /*modfied by tbl for increase prepare timing*/
    {0x0129, 0x10},

    {0x0180, 0x4f},
    {0x0181, 0x30},
    {0x0182, 0x05},
    {0x0185, 0x01},
    {0x03fe, 0x10},
    {0x03fe, 0x00},
    {0x0100, 0x09},

};

static const SNS_REG_S s_aRaw10b2560X144030fps2Lane[] = {
    /****************************************/
    //version 6.8
    //mclk 24Mhz
    //mipi_data_rate 648Mbps
    //framelength 1500
    //linelength 4800
    //pclk 216Mhz
    //rowtime 22.2222us
    //pattern grbg

    {0x03fe,  0xf0},
    {0x03fe,  0x00},
    {0x0317,  0x00},
    {0x0320,  0x77},
    {0x0324,  0xc8},
    {0x0325,  0x06},
    {0x0326,  0x6c},
    {0x0327,  0x03},
    {0x0334,  0x40},
    {0x0336,  0x6c},
    {0x0337,  0x82},
    {0x0315,  0x25},
    {0x031c,  0xc6},
    {0x0287,  0x18},
    {0x0084,  0x00},
    {0x0087,  0x50},
    {0x029d,  0x08},
    {0x0290,  0x00},
    {0x0340,  0x05},
    {0x0341,  0xdc},
    {0x0345,  0x06},
    {0x034b,  0xb0},
    {0x0352,  0x08},
    {0x0354,  0x08},
    {0x02d1,  0xe0},
    {0x0223,  0xf2},
    {0x0238,  0xa4},
    {0x02ce,  0x7f},
    {0x0232,  0xc4},
    {0x02d3,  0x05},
    {0x0243,  0x06},
    {0x02ee,  0x30},
    {0x026f,  0x70},
    {0x0257,  0x09},
    {0x0211,  0x02},
    {0x0219,  0x09},
    {0x023f,  0x2d},
    {0x0518,  0x00},
    {0x0519,  0x01},
    {0x0515,  0x08},
    {0x02d9,  0x3f},
    {0x02da,  0x02},
    {0x02db,  0xe8},
    {0x02e6,  0x20},
    {0x021b,  0x10},
    {0x0252,  0x22},
    {0x024e,  0x22},
    {0x02c4,  0x01},
    {0x021d,  0x17},
    {0x024a,  0x01},
    {0x02ca,  0x02},
    {0x0262,  0x10},
    {0x029a,  0x20},
    {0x021c,  0x0e},
    {0x0298,  0x03},
    {0x029c,  0x00},
    {0x027e,  0x14},
    {0x02c2,  0x10},
    {0x0540,  0x20},
    {0x0546,  0x01},
    {0x0548,  0x01},
    {0x0544,  0x01},
    {0x0242,  0x1b},
    {0x02c0,  0x1b},
    {0x02c3,  0x20},
    {0x02e4,  0x10},
    {0x022e,  0x00},
    {0x027b,  0x3f},
    {0x0269,  0x0f},
    {0x02d2,  0x40},
    {0x027c,  0x08},
    {0x023a,  0x2b},
    {0x0245,  0xcb},
    {0x0530,  0x20},
    {0x0531,  0x02},
    {0x0228,  0x3e},
    {0x02ab,  0x00},
    {0x0250,  0x00},
    {0x0221,  0x50},
    {0x02ac,  0x00},
    {0x02a5,  0x02},
    {0x0260,  0x0b},
    {0x0216,  0x04},
    {0x0299,  0x1C},
    {0x02bb,  0x0d},
    {0x02a3,  0x02},
    {0x02a4,  0x02},
    {0x021e,  0x02},
    {0x024f,  0x08},
    {0x028c,  0x08},
    {0x0532,  0x3f},
    {0x0533,  0x02},
    {0x0277,  0x92},
    {0x0276,  0x92},
    {0x0239,  0xc0},
    {0x0202,  0x05},
    {0x0203,  0xd0},
    {0x0205,  0xc0},
    {0x02b0,  0x68},
    {0x0002,  0xa9},
    {0x0004,  0x01},
    {0x021a,  0x98},
    {0x0266,  0xa0},
    {0x0020,  0x01},
    {0x0021,  0x03},
    {0x0022,  0x00},
    {0x0023,  0x04},
    {0x0342,  0x06},
    {0x0343,  0x40},
    {0x03fe,  0x10},
    {0x03fe,  0x00},
    {0x0106,  0x78},
    {0x0108,  0x0c},
    {0x0114,  0x01},
    {0x0115,  0x12},
    {0x0180,  0x46},
    {0x0181,  0x30},
    {0x0182,  0x05},
    {0x0185,  0x01},
    {0x03fe,  0x10},
    {0x03fe,  0x00},
    {0x0100,  0x09},
    {0x012b,  0x30}, /* add Ths-trail */
    {0x0080,  0x02},
    {0x0097,  0x0a},
    {0x0098,  0x10},
    {0x0099,  0x05},
    {0x009a,  0xb0},
    {0x0317,  0x08},
    {0x0a67,  0x80},
    {0x0a70,  0x03},
    {0x0a82,  0x00},
    {0x0a83,  0x10},
    {0x0a80,  0x2b},
    {0x05be,  0x00},
    {0x05a9,  0x01},
    {0x0313,  0x80},
    {0x05be,  0x01},
    {0x0317,  0x00},
    {0x0a67,  0x00},
};


static const SNS_REG_S s_aRaw10b2560X1440p15fps2Lane[] = {
    /* only 100k i2c */
    //version 6.8
    //mclk 24Mhz
    //mipidata rate=432Mbps/lane
    //framelength 1500
    //linelength 4800
    //pclk 144Mhz
    //rowtime 33.333us
    //pattern grbg
    {0x03fe,0xf0},
    {0x03fe,0x00},
    {0x0317,0x00},
    {0x0320,0x77},
    {0x0324,0xc8},
    {0x0325,0x06},
    {0x0326,0x48},
    {0x0327,0x03},
    {0x0334,0x40},
    {0x0336,0x48},
    {0x0337,0x82},
    {0x0315,0x25},
    {0x031c,0xc6},
    {0x0287,0x18},
    {0x0084,0x00},
    {0x0087,0x50},
    {0x029d,0x08},
    {0x0290,0x00},
    {0x0340,0x05},
    {0x0341,0xdc},
    {0x0345,0x06},
    {0x034b,0xb0},
    {0x0352,0x08},
    {0x0354,0x08},
    {0x02d1,0xe0},
    {0x0223,0xf2},
    {0x0238,0xa4},
    {0x02ce,0x7f},
    {0x0232,0xc4},
    {0x02d3,0x05},
    {0x0243,0x06},
    {0x02ee,0x30},
    {0x026f,0x70},
    {0x0257,0x09},
    {0x0211,0x02},
    {0x0219,0x09},
    {0x023f,0x2d},
    {0x0518,0x00},
    {0x0519,0x01},
    {0x0515,0x08},
    {0x02d9,0x3f},
    {0x02da,0x02},
    {0x02db,0xe8},
    {0x02e6,0x20},
    {0x021b,0x10},
    {0x0252,0x22},
    {0x024e,0x22},
    {0x02c4,0x01},
    {0x021d,0x17},
    {0x024a,0x01},
    {0x02ca,0x02},
    {0x0262,0x10},
    {0x029a,0x20},
    {0x021c,0x0e},
    {0x0298,0x03},
    {0x029c,0x00},
    {0x027e,0x14},
    {0x02c2,0x10},
    {0x0540,0x20},
    {0x0546,0x01},
    {0x0548,0x01},
    {0x0544,0x01},
    {0x0242,0x1b},
    {0x02c0,0x1b},
    {0x02c3,0x20},
    {0x02e4,0x10},
    {0x022e,0x00},
    {0x027b,0x3f},
    {0x0269,0x0f},
    {0x02d2,0x40},
    {0x027c,0x08},
    {0x023a,0x2e},
    {0x0245,0xce},
    {0x0530,0x20},
    {0x0531,0x02},
    {0x0228,0x50},
    {0x02ab,0x00},
    {0x0250,0x00},
    {0x0221,0x50},
    {0x02ac,0x00},
    {0x02a5,0x02},
    {0x0260,0x0b},
    {0x0216,0x04},
    {0x0299,0x1c},
    {0x02bb,0x0d},
    {0x02a3,0x02},
    {0x02a4,0x02},
    {0x021e,0x02},
    {0x024f,0x08},
    {0x028c,0x08},
    {0x0532,0x3f},
    {0x0533,0x02},
    {0x0277,0xc0},
    {0x0276,0xc0},
    {0x0239,0xc0},
    {0x0202,0x05},
    {0x0203,0xd0},
    {0x0205,0xc0},
    {0x02b0,0x75},
    {0x0002,0xa9},
    {0x0004,0x01},

    {0x021a,0x98},
    {0x0266,0xa0},
    {0x0020,0x01},
    {0x0021,0x03},
    {0x0022,0x00},

    {0x0023,0x04},
    //0x0342,0x06,//20fps-HTS
    //0x0343,0x40,//20fps-HTS
    {0x0342,0x08},//15fps//0x21,//modefied by tbl 20210915
    {0x0343,0x54},//15fps//0x32,//modefied by tbl 20210915
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0106,0x78},
    {0x0108,0x0c},
    {0x0114,0x01},
    {0x0115,0x12},
    {0x0180,0x46},
    {0x0181,0x30},
    {0x0182,0x05},
    {0x0185,0x01},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0101,0x00},
    {0x0100,0x09},
    {0x000f,0x00},

    {0x0277,0x38},
    {0x0276,0xc0},
    {0x000f,0x10},
    {0x0059,0x00},
        //otp
    {0x0080,0x02},
    {0x0097,0x0a},
    {0x0098,0x10},
    {0x0099,0x05},
    {0x009a,0xb0},
    {0x0317,0x08},
    {0x0a67,0x80},
    {0x0a70,0x03},
    {0x0a82,0x00},
    {0x0a83,0x10},
    {0x0a80,0x2b},
    {0x05be,0x00},
    {0x05a9,0x01},
    {0x0313,0x80},
    {0x05be,0x01},
    {0x0317,0x00},
    {0x0a67,0x00},

    {0x0182,0x05},
    {0x0185,0x01},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0100,0x09},
    //{0x000f,0x00},

};

static const SNS_REG_S s_aRaw1080p60fps[] = {
    {0x03fe,0xf0},
    {0x03fe,0x00},
    {0x0317,0x00},
    {0x0320,0x77},
    {0x0324,0xc8},
    {0x0325,0x05},
    {0x0326,0x60},
    {0x0327,0x03},
    {0x0334,0x40},
    {0x0335,0xd1},
    {0x0336,0x50},
    {0x0337,0x82},
    {0x0315,0x25},
    {0x031c,0xc6},
    {0x0287,0x18},
    {0x0084,0x00},
    {0x0087,0x50},
    {0x029d,0x08},
    {0x0290,0x00},
    {0x0340,0x04},
    {0x0341,0xe2},
    {0x0344,0x00},//window
    {0x0345,0x06},
    {0x0346,0x00},
    {0x0347,0xb4},
    {0x0348,0x0a},
    {0x0349,0x10},
    {0x034a,0x04},
    {0x034b,0x48},
    {0x0351,0x00},//crop
    {0x0352,0x08},
    {0x0353,0x01},
    {0x0354,0x40},
    {0x034c,0x07},
    {0x034d,0x80},//  1920
    {0x034e,0x04},
    {0x034f,0x38},//  1080
    {0x02d1,0xe0},
    {0x0223,0xf2},
    {0x0238,0xa4},
    {0x02ce,0x7f},
    {0x0232,0xc4},
    {0x02d3,0x05},
    {0x0243,0x06},
    {0x02ee,0x30},
    {0x026f,0x70},
    {0x0257,0x09},
    {0x0211,0x02},
    {0x0219,0x09},
    {0x023f,0x2d},
    {0x0518,0x00},
    {0x0519,0x01},
    {0x0515,0x08},
    {0x02d9,0x3f},
    {0x02da,0x02},
    {0x02db,0xe8},
    {0x02e6,0x20},
    {0x021b,0x10},
    {0x0252,0x22},
    {0x024e,0x22},
    {0x02c4,0x01},
    {0x021d,0x17},
    {0x024a,0x01},
    {0x02ca,0x02},
    {0x0262,0x10},
    {0x029a,0x20},
    {0x021c,0x0e},
    {0x0298,0x03},
    {0x029c,0x00},
    {0x027e,0x14},
    {0x02c2,0x10},
    {0x0540,0x20},
    {0x0546,0x01},
    {0x0548,0x01},
    {0x0544,0x01},
    {0x0242,0x1b},
    {0x02c0,0x1b},
    {0x02c3,0x20},
    {0x02e4,0x10},
    {0x022e,0x00},
    {0x027b,0x3f},
    {0x0269,0x0f},
    {0x000f,0x00},
    {0x02d2,0x40},
    {0x027c,0x08},
    {0x023a,0x2e},
    {0x0245,0xce},
    {0x0530,0x20},
    {0x0531,0x02},
    {0x0228,0x50},
    {0x02ab,0x00},
    {0x0250,0x00},
    {0x0221,0x50},
    {0x02ac,0x00},
    {0x02a5,0x02},
    {0x0260,0x0b},
    {0x0216,0x04},
    {0x0299,0x1C},
    {0x02bb,0x0d},
    {0x02a3,0x02},
    {0x02a4,0x02},
    {0x021e,0x02},
    {0x024f,0x08},
    {0x028c,0x08},
    {0x0532,0x3f},
    {0x0533,0x02},
    {0x0277,0x60},
    {0x0276,0x60},
    {0x0239,0xc0},
    {0x0202,0x05},
    {0x0203,0x46},
    {0x0205,0xc0},
    {0x02b0,0x68},
    {0x0002,0xa9},
    {0x0004,0x01},
    {0x0005,0x8a},
    {0x0006,0xe0},
    {0x0007,0x65},
    {0x0008,0x66},
    {0x0009,0x56},
    {0x000a,0x55},
    {0x0266,0xc0},
    {0x0021,0x04},
    {0x0022,0x00},
    {0x021a,0x98},
    {0x0020,0x01},
    {0x0023,0x08},
    {0x0023,0x00},
    {0x0342,0x05},
    {0x0343,0xa0},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0104,0x20},
    {0x0105,0x20},
    {0x0106,0x78},
    {0x0108,0x0c},
    {0x0114,0x01},
    {0x0115,0x12},
    {0x0180,0x66},
    {0x0181,0x30},
    {0x0182,0x05},
    {0x0185,0x01},
    {0x03fe,0x10},
    {0x03fe,0x00},
    {0x0100,0x09},
    //otp
    {0x0080,0x02},
    {0x0097,0x0a},
    {0x0098,0x10},
    {0x0099,0x05},
    {0x009a,0xb0},
    {0x0317,0x08},
    {0x0a67,0x80},
    {0x0a70,0x03},
    {0x0a82,0x00},
    {0x0a83,0x10},
    {0x0a80,0x2b},
    {0x05be,0x00},
    {0x05a9,0x01},
    {0x0313,0x80},
    {0x05be,0x01},
    {0x0317,0x00},
    {0x0a67,0x00},
};

static CAMERA_POWER_ACT_S s_stPowerUpAct[] = {
    {SNS_RESET,  SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_PWDN, SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_RESET, SNS_UP},
    {SNS_DELAY, 20},
    {SNS_PWDN,  SNS_UP},
    {SNS_DELAY, 20},
};

static CAMERA_POWER_ACT_S s_sPowerDownAct[] = {
    {SNS_PWDN, SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_RESET,  SNS_DOWN},
};

/*vts:{0x0340,0x0341}
 *hts:{0x033f,0x033e}
 */
static SNS_TYPE_ATTR_S s_astSnsAttr[] = {
    {
        .enSnsType                  = GC4663_MIPI_1920_1080_30FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 1500 * 1428 * 30,
        .u32Vts                     = 1500,
        .u32Hts                     = 1428,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108030fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108030fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 404352000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_1920_1080_60FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 27000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 160000000,
        .u32IppuClk                 = 320000000,

        .u32Pclk                    = 1250 * 1428 * 60,
        .u32Vts                     = 1250,
        .u32Hts                     = 1428,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 60,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p60fps,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p60fps),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 1080*1000*1000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_1920_1080_2TO1_30FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_VC,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 1600 * 1428 * 30 * 2,
        .u32Vts                     = 1600,
        .u32Hts                     = 1428,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108030fps2Lane2to1,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108030fps2Lane2to1),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 404352000 * 2,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = GC4663_MIPI_2560_1440_15FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {2560, 1440},
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,

        .u32Pclk                    = 108000000,
        .u32Vts                     = 1500,
        .u32Hts                     = 4800,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 15,
        .astRegCfgs[0].pstRegs      = s_aRaw10b2560X1440p15fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b2560X1440p15fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 423000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_2560_1440_30FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {2560, 1440},
        .u32ModuleClk               = 297000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 148000000,
        .u32IppuClk                 = 297000000,
        .u32Pclk                    = 64260000,
        .u32Vts                     = 1500,
        .u32Hts                     = 1428,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b2560X144030fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b2560X144030fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 648000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_2560_1440_25FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {2560, 1440},
        .u32ModuleClk               = 297000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 148000000,
        .u32IppuClk                 = 297000000,
        .u32Pclk                    = 64260000,
        .u32Vts                     = 1800,//1800 708
        .u32Hts                     = 1428,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw10b2560X144030fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b2560X144030fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 648000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_2560_1440_2TO1_30FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {2560, 1440},
        .u32ModuleClk               = 396000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_VC,

        .u32IspClk                  = 160000000,
        .u32IppuClk                 = 320000000,
        .u32Pclk                    = 132000000,
        .u32Vts                     = 1600,
        .u32Hts                     = 2750,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b2560X144030fps2Lane2to1,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b2560X144030fps2Lane2to1),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 1344000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },

    {
        .enSnsType                  = GC4663_MIPI_2560_1440_2TO1_25FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_GRBG,
        .stSize                     = {2560, 1440},
        .u32ModuleClk               = 396000000,
        .u32Mclock                  = 24000000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_VC,

        .u32IspClk                  = 160000000,
        .u32IppuClk                 = 320000000,
        .u32Pclk                    = 132000000,
        .u32Vts                     = 1920,
        .u32Hts                     = 2750,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw10b2560X144030fps2Lane2to1,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b2560X144030fps2Lane2to1),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 1344000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
};

static int CAMERA_SetI2cInfo(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    if (pstSnsState->stI2cInfo.fd > 0) {
        return EI_SUCCESS;
    }

    pstSnsState->stI2cInfo.u8RegBits = 16;
    pstSnsState->stI2cInfo.u8ValBits = 8;
    pstSnsState->stI2cInfo.u16I2cBusNum = 4;
    pstSnsState->stI2cInfo.u16I2cDevAddr = 0x29;
    pstSnsState->pcName = SNS_NAME;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Detect(VISS_DEV VissDev)
{

    EI_U8 u8Tmp[2];
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U16 u16Id;
    SNS_STATE_S *pstSnsState = EI_NULL;
    I2C_INFO_S *pstI2cInfo = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    CAMERA_CHECK_POINTER(pstI2cInfo->pfnReadReg);
    s32Ret = pstI2cInfo->pfnReadReg(pstSnsState, 0x03f1, &u8Tmp[0]);
    if (s32Ret != 0) {
        PRT_VISS_ERR("tmp[0]=%x\n", u8Tmp[0]);
        return EI_FAILURE;
    }
    s32Ret = pstI2cInfo->pfnReadReg(pstSnsState, 0x03f0, &u8Tmp[1]);
    if (s32Ret != 0) {
        PRT_VISS_ERR("tmp[0]=%x,tmp[1]=%x\n", u8Tmp[0], u8Tmp[1]);
        return EI_FAILURE;
    }
    u16Id = (u8Tmp[0] << 8) | u8Tmp[1];
    PRT_VISS_INFO("id: 0x%04x.\n", u16Id);

    if (u16Id != 0x5346) {
        PRT_VISS_ERR("ID wrong! (0x%04x != 0x4653)\n", u16Id);
        return EI_FAILURE;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Stream(VISS_DEV dev, EI_BOOL bOn)
{
    PRT_VISS_INFO("CAMERA_Stream*******%d\n", bOn);
    return EI_SUCCESS;
}

/* The following functions can be modified as needed */

static int CAMERA_I2cInit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    int ret = EI_SUCCESS;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    ret = CAMERA_SetI2cInfo(dev);
    CAMERA_CHECK_SUCCESS(ret);

    ret = CAMERA_I2C_Reg_Ops(&pstSnsState->stI2cInfo);
    CAMERA_CHECK_SUCCESS(ret);

    return EI_SUCCESS;
}

static int CAMERA_I2cExit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_PowerUp(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    CAMERA_SensorPowerUp(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_PowerDown(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    CAMERA_SensorPowerDown(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_MirrorFlip(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    I2C_INFO_S *pstI2cInfo = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Tmp = 0;

    SNS_GET_CTX(VissDev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    PRT_VISS_INFO("%s set mirror[%d] flip[%d] \n", SNS_NAME,
        pstSnsState->u32SnsMirror, pstSnsState->u32SnsFlip);

    if (!pstSnsState->u32SnsMirror && !pstSnsState->u32SnsFlip) {
        s32Ret = pstI2cInfo->pfnWriteReg(pstSnsState, 0x0101, (u32Tmp & 0xfc ) | 0x00);
        if (s32Ret != 0) {
            PRT_VISS_ERR("%s pfnWriteReg error\n", SNS_NAME);
            return s32Ret;
        }
        return s32Ret;
    }

    /* sensor flip & mirror */
    pstI2cInfo->pfnReadReg(pstSnsState, 0x0101, &u32Tmp);
    if (s32Ret != 0) {
        PRT_VISS_ERR("%s pfnReadReg error\n", SNS_NAME);
        return s32Ret;
    }

    if (pstSnsState->u32SnsMirror) {
        s32Ret = pstI2cInfo->pfnWriteReg(pstSnsState, 0x0101, (u32Tmp & 0xfe ) | 0x01);
    } else {
        s32Ret = pstI2cInfo->pfnWriteReg(pstSnsState, 0x0101, (u32Tmp & 0xfe ));
    }
    if (s32Ret != 0) {
        PRT_VISS_ERR("%s pfnWriteReg error\n", SNS_NAME);
        return s32Ret;
    }

    pstI2cInfo->pfnReadReg(pstSnsState, 0x0101, &u32Tmp);
    if (s32Ret != 0) {
        PRT_VISS_ERR("%s pfnReadReg error\n", SNS_NAME);
        return s32Ret;
    }

    if (pstSnsState->u32SnsFlip) {
        s32Ret = pstI2cInfo->pfnWriteReg(pstSnsState, 0x0101, (u32Tmp & 0xfd ) | 0x02);
    } else {
        s32Ret = pstI2cInfo->pfnWriteReg(pstSnsState, 0x0101, (u32Tmp & 0xfd ));
    }
    if (s32Ret != 0) {
        PRT_VISS_ERR("%s pfnWriteReg error\n", SNS_NAME);
        return s32Ret;
    }

    return s32Ret;
}

static EI_S32 CAMERA_SetGain(ISP_DEV dev, EI_FLOAT fGain);
static EI_S32 CAMERA_SetExpTime(ISP_DEV dev, EI_FLOAT *afIntTime);

static EI_S32 CAMERA_Init(VISS_DEV dev)
{
    EI_U32 j;
    const SNS_TYPE_ATTR_S *pstSnsType;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret;
    I2C_INFO_S *pstI2cInfo = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    pstSnsType = pstSnsState->pstSnsAttr;
    for (j = 0; j < MAX_COF; j++) {
        s32Ret = pstSnsState->stI2cInfo.pfnwriteRegList(pstSnsState,
                pstSnsType->astRegCfgs[j].pstRegs, pstSnsType->astRegCfgs[j].u32RegsCnt);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("%s writeRegList err\n", SNS_NAME);
            return s32Ret;
        }
    }

    if(pstSnsType->enSnsType == GC4663_MIPI_2560_1440_25FPS_RAW10 ||
        pstSnsType->enSnsType == GC4663_MIPI_2560_1440_2TO1_25FPS_RAW10) {
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0340, (pstSnsType->u32Vts >> 8));
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0341, pstSnsType->u32Vts & 0xff);
        if (s32Ret != 0) {
            PRT_VISS_ERR("CAMERA_Init error\n");
            return s32Ret;
        }
    }


    if ((pstSnsState->afIntTime[0] > 0.000001) && (pstSnsState->fGain >= 1.0)) {
        CAMERA_SetExpTime(pstSnsState->IspDev, pstSnsState->afIntTime);
        CAMERA_SetGain(pstSnsState->IspDev, pstSnsState->fGain);
    }

    CAMERA_MirrorFlip(dev);

    PRT_VISS_INFO("%s writeRegList success\n", SNS_NAME);

    return s32Ret;
}

static void CAMERA_Exit(VISS_DEV dev)
{
    CAMERA_I2cExit(dev);

    return ;
}

static EI_S32 CAMERA_SetImageMode(VISS_DEV dev, SNS_TYPE_E enSnsType)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstSnsState->enSnsType = enSnsType;
    pstSnsState->bSyncInit = EI_FALSE;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_EnumSnstype(VISS_DEV VissDev, EI_U32 u32Index, SNS_TYPE_E *peSnstype)
{
    const SNS_TYPE_ATTR_S *pstSnsType;

    if (u32Index >= ARRAY_SIZE(s_astSnsAttr))
        return EN_ERR_NO_FOUND;

    pstSnsType = &s_astSnsAttr[u32Index];

    *peSnstype = pstSnsType->enSnsType;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFrameRate(VISS_DEV VissDev, EI_FLOAT f32Fps)
{
    I2C_INFO_S *pstI2cInfo = EI_NULL;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts;

    SNS_GET_CTX(VissDev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;
    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Hts = pstSnsState->pstSnsAttr->u32Hts;

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Vts = u32Pclk / u32Hts / f32Fps;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0340, u32Vts >> 8);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0341, u32Vts);

        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Vts = u32Pclk / u32Hts / f32Fps;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0340, u32Vts >> 8);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0341, u32Vts);

        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else {
        return EN_ERR_NOT_SUPPORT;
    }

    pstSnsState->pstSnsAttr->u32Vts = u32Vts;

    return EI_SUCCESS;

}

static EI_S32 CAMERA_InitSensorExpFunction(SENSOR_EXP_FUNC_S *pstSensorExpFunc)
{
    CAMERA_CHECK_POINTER(pstSensorExpFunc);

    memset(pstSensorExpFunc, 0, sizeof(SENSOR_EXP_FUNC_S));

    pstSensorExpFunc->pfnSensorPowerUp  = CAMERA_PowerUp;
    pstSensorExpFunc->pfnSensorPowerDown = CAMERA_PowerDown;
    pstSensorExpFunc->pfnSensorDetect   = CAMERA_Detect;
    pstSensorExpFunc->pfnSensorInit     = CAMERA_Init;
    pstSensorExpFunc->pfnSensorStream   = CAMERA_Stream;
    pstSensorExpFunc->pfnSensorExit     = CAMERA_Exit;
    pstSensorExpFunc->pfnSensorSetImageMode   = CAMERA_SetImageMode;
    pstSensorExpFunc->pfnSensorEnumSnstype   = CAMERA_EnumSnstype;
    pstSensorExpFunc->pfnSensorSetFrameRate   = CAMERA_SetFrameRate;
    pstSensorExpFunc->pfnSensorSetMirrorFlip = CAMERA_MirrorFlip;
    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAeDefault(ISP_DEV dev, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{

    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFps(ISP_DEV dev, EI_FLOAT f32Fps, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return CAMERA_SetFrameRate(Dev, f32Fps);
}

static EI_S32 CAMERA_SetExpTime(ISP_DEV dev, EI_FLOAT *afIntTime)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts, u32Vmax;
    EI_U32 shutter_time;
    EI_U32 u32Lexp, u32Mexp;
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    CAMERA_CHECK_POINTER(afIntTime);

    pstSnsState->afIntTime[0] = afIntTime[0];
    pstSnsState->afIntTime[1] = afIntTime[1];
    pstSnsState->afIntTime[2] = afIntTime[2];
    pstSnsState->afIntTime[3] = afIntTime[3];
    pstSnsState->IspDev = dev;
    if (pstSnsState->bPower == EI_FALSE) {
        return EI_SUCCESS;
    }

    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Hts = pstSnsState->pstSnsAttr->u32Hts;
    u32Vts = pstSnsState->pstSnsAttr->u32Vts;

    if ((u32Pclk == 0) || (u32Hts == 0) || (u32Vts == 0)) {
        PRT_VISS_ERR("error! u32Pclk %d, u32Hts %d, u32Vts %d\n", u32Pclk, u32Hts, u32Vts);
        return EI_FAILURE;
    }

    /* afIntTime[0] long/medium/short/vshort exptime (s) */
    shutter_time = afIntTime[0] * u32Pclk / u32Hts;

    //printf("exp_time: %d, %f(s)!\n", shutter_time, afIntTime[0]);

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {

        if (shutter_time > u32Vts)
            u32Vmax = shutter_time;
        else
            u32Vmax = u32Vts;

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0340, u32Vmax >> 8);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0341, u32Vmax);

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0203, (shutter_time) & 0xff);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0202, (shutter_time >> 8) & 0x3f);

        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }

    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {

        if (afIntTime[1] < 1) {
            afIntTime[1] = 8;
        }

        /* shutter_time = u32Lexp + u32Mexp */
        /* short_exp + long_exp < (vts - 8) */
        if (shutter_time > (pstSnsState->pstSnsAttr->u32Vts - 8)) {
            shutter_time = pstSnsState->pstSnsAttr->u32Vts - 8;
        }

        u32Mexp = shutter_time / (afIntTime[1] + 1);
        if (u32Mexp < 1) {
            u32Mexp = 1;
        }

        u32Lexp = u32Mexp * afIntTime[1];

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0202, (u32Lexp >> 8) & 0x3f);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0203, (u32Lexp & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0200, (u32Mexp >> 8) & 0x3f);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0201, (u32Mexp & 0xff));

        shutter_time = u32Lexp;

        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }
    }

    afIntTime[0] = (EI_FLOAT)(shutter_time) * u32Hts / u32Pclk;
    if (afIntTime[0] < 0.00001) {
        afIntTime[0] = 0.00001;
    }

    return s32Ret;
}

static EI_U32 WdrRegValTable[21][7] = {
    //2b3 2b4  2b8	2b9  515  519  2d9
    {0x00,0x00,0x01,0x00,0x30,0x28,0x66},
    {0x20,0x00,0x01,0x0B,0x30,0x2a,0x68},
    {0x01,0x00,0x01,0x19,0x30,0x27,0x65},
    {0x21,0x00,0x01,0x2A,0x30,0x29,0x67},
    {0x02,0x00,0x02,0x00,0x30,0x27,0x65},
    {0x22,0x00,0x02,0x17,0x30,0x29,0x67},
    {0x03,0x00,0x02,0x33,0x30,0x28,0x66},
    {0x23,0x00,0x03,0x14,0x30,0x2a,0x68},
    {0x04,0x00,0x04,0x00,0x30,0x2a,0x68},
    {0x24,0x00,0x04,0x2F,0x30,0x2b,0x69},
    {0x05,0x00,0x05,0x26,0x30,0x2c,0x6A},
    {0x25,0x00,0x06,0x28,0x30,0x2e,0x6C},
    {0x06,0x00,0x08,0x00,0x30,0x2f,0x6D},
    {0x26,0x00,0x09,0x1E,0x30,0x31,0x6F},
    {0x46,0x00,0x0B,0x0C,0x30,0x34,0x72},
    {0x66,0x00,0x0D,0x11,0x30,0x37,0x75},
    {0x0e,0x00,0x10,0x00,0x30,0x3a,0x78},
    {0x2e,0x00,0x12,0x3D,0x30,0x3e,0x7C},
    {0x4e,0x00,0x16,0x19,0x30,0x41,0x7F},
    {0x6e,0x00,0x1A,0x22,0x30,0x45,0x83},
    {0x1e,0x00,0x20,0x00,0x30,0x49,0x87},
};

static EI_U32 LinerRegValTable[26][7] = {
//2b3    2b4    2b8    2b9    515    519    2d9
    {0x00,  0x00,  0x01,  0x00,  0x30,  0x1e,  0x5C},
    {0x20,  0x00,  0x01,  0x0B,  0x30,  0x1e,  0x5C},
    {0x01,  0x00,  0x01,  0x19,  0x30,  0x1d,  0x5B},
    {0x21,  0x00,  0x01,  0x2A,  0x30,  0x1e,  0x5C},
    {0x02,  0x00,  0x02,  0x00,  0x30,  0x1e,  0x5C},
    {0x22,  0x00,  0x02,  0x17,  0x30,  0x1d,  0x5B},
    {0x03,  0x00,  0x02,  0x33,  0x20,  0x16,  0x54},
    {0x23,  0x00,  0x03,  0x14,  0x20,  0x17,  0x55},
    {0x04,  0x00,  0x04,  0x00,  0x20,  0x17,  0x55},
    {0x24,  0x00,  0x04,  0x2F,  0x20,  0x19,  0x57},
    {0x05,  0x00,  0x05,  0x26,  0x20,  0x19,  0x57},
    {0x25,  0x00,  0x06,  0x28,  0x20,  0x1b,  0x59},
    {0x0c,  0x00,  0x08,  0x00,  0x20,  0x1d,  0x5B},
    {0x2C,  0x00,  0x09,  0x1E,  0x20,  0x1f,  0x5D},
    {0x0D,  0x00,  0x0B,  0x0C,  0x20,  0x21,  0x5F},
    {0x2D,  0x00,  0x0D,  0x11,  0x20,  0x24,  0x62},
    {0x1C,  0x00,  0x10,  0x00,  0x20,  0x26,  0x64},
    {0x3C,  0x00,  0x12,  0x3D,  0x18,  0x2a,  0x68},
    {0x5C,  0x00,  0x16,  0x19,  0x18,  0x2c,  0x6A},
    {0x7C,  0x00,  0x1A,  0x22,  0x18,  0x2e,  0x6C},
    {0x9C,  0x00,  0x20,  0x00,  0x18,  0x32,  0x70},
    {0xBC,  0x00,  0x25,  0x3A,  0x18,  0x35,  0x73},
    {0xDC,  0x00,  0x2C,  0x33,  0x10,  0x36,  0x74},
    {0xFC,  0x00,  0x35,  0x05,  0x10,  0x38,  0x76},
    {0x1C,  0x01,  0x40,  0x00,  0x10,  0x3c,  0x7A},
    {0x3C,  0x01,  0x4B,  0x35,  0x10,  0x42,  0x80},
};

static EI_U32 analog_gain_table_wdr[22] = {
    64, 75, 89, 106,
    128, 151, 179, 212,
    256, 303, 358, 424,
    512, 606, 716, 849,
    1024, 1213, 1433, 1698,
    2048, 0xffffffff,
};

static EI_U32 analog_gain_table_linear[27] = {
    64, 75, 89, 106,
    128, 151, 179, 212,
    256, 303, 358, 424,
    512, 606, 716, 849,
    1024, 1213, 1433, 1698,
    2048, 2426, 2867, 3397,
    4096, 4853, 0xffffffff,
};

static EI_S32 CAMERA_SetGain(ISP_DEV dev, EI_FLOAT fGain)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U8 total;
    EI_U8 i;
    EI_U32 tol_dig_gain;
    EI_U32 u32Gain;
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstSnsState->fGain = fGain;
    if (pstSnsState->bPower == EI_FALSE) {
        return EI_SUCCESS;
    }

    u32Gain = fGain * 64;

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {

        total = sizeof(analog_gain_table_linear) / sizeof(EI_U32);
        for(i = 0; i < total; i++) {
            if((analog_gain_table_linear[i] <= u32Gain) &&
                (u32Gain < analog_gain_table_linear[i + 1]))
                break;
        }

        tol_dig_gain = u32Gain * 64 / analog_gain_table_linear[i];

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b3, LinerRegValTable[i][0]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b4, LinerRegValTable[i][1]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b8, LinerRegValTable[i][2]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b9, LinerRegValTable[i][3]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x515, LinerRegValTable[i][4]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x519, LinerRegValTable[i][5]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2D9, LinerRegValTable[i][6]);
    } else {

        total = sizeof(analog_gain_table_wdr) / sizeof(EI_U32);
        for(i = 0; i < total; i++) {
            if((analog_gain_table_wdr[i] <= u32Gain) &&
                (u32Gain < analog_gain_table_wdr[i + 1]))
                break;
        }

        tol_dig_gain = u32Gain * 64 / analog_gain_table_wdr[i];

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b3, WdrRegValTable[i][0]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b4, WdrRegValTable[i][1]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b8, WdrRegValTable[i][2]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2b9, WdrRegValTable[i][3]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x515, WdrRegValTable[i][4]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x519, WdrRegValTable[i][5]);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x2D9, WdrRegValTable[i][6]);
    }

    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x20e, (tol_dig_gain >> 6));
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x20f, ((tol_dig_gain & 0x3f) << 2));

    if (s32Ret != EI_SUCCESS) {
        PRT_VISS_ERR("\n");
    }

    return s32Ret;
}

static EI_S32 CAMERA_InitAeExpFunction(AE_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S));

    pstExpFuncs->pfnGetAeDefault    = CAMERA_GetAeDefault;
    pstExpFuncs->pfnSetFps          = CAMERA_SetFps;
    pstExpFuncs->pfnSetExpTime      = CAMERA_SetExpTime;
    pstExpFuncs->pfnSetGain         = CAMERA_SetGain;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAwbDefault(ISP_DEV dev, AWB_SENSOR_DEFAULT_S *pstAwbSnsDft)
{
    CAMERA_CHECK_POINTER(pstAwbSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_InitAwbExpFunction(AWB_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S));
    pstExpFuncs->pfnGetAwbDefault = CAMERA_GetAwbDefault;

    return EI_SUCCESS;
}

/****************************************************************************
 * callback structure                                                       *
 ****************************************************************************/

static EI_S32 CAMERA_CtxInit(VISS_DEV dev)
{
    SNS_STATE_S *pastSnsStateCtx = EI_NULL;

    SNS_GET_CTX(dev, pastSnsStateCtx);

    CAMERA_CHECK_POINTER(pastSnsStateCtx);

    memset(pastSnsStateCtx, 0, sizeof(SNS_STATE_S));

    pastSnsStateCtx->pstPowerUpAct      = s_stPowerUpAct;
    pastSnsStateCtx->pstPowerDownAct    = s_sPowerDownAct;
    pastSnsStateCtx->u8PwrUpActs        = ARRAY_SIZE(s_stPowerUpAct);
    pastSnsStateCtx->u8PwrDnActs        = ARRAY_SIZE(s_sPowerDownAct);

    return EI_SUCCESS;
}

static EI_VOID CAMERA_CtxExit(VISS_DEV dev)
{
    return ;
}

static EI_S32 CAMERA_RegisterVissCallback(VISS_DEV dev, SNS_TYPE_E enType)
{
    EI_S32 s32Ret;
    SENSOR_S stSns = {0};
    EI_U32 i;
    SNS_STATE_S *pstSnsState = EI_NULL;

    s32Ret = CAMERA_CtxInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    SNS_GET_CTX(dev, pstSnsState);

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsState->pstSnsAttr = &s_astSnsAttr[i];
            break;
        }
    }

    pstSnsState->enSnsType = enType;
    pstSnsState->Dev = dev;

    if (i >= ARRAY_SIZE(s_astSnsAttr)) {
        PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);
        return EI_FAILURE;
    }

    s32Ret = CAMERA_I2cInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    stSns.stSnsAttrInfo.eSensorId = SNS_ID;
    stSns.stSnsAttrInfo.enDevType = DEV_TYPE;
    stSns.stSnsAttrInfo.pstSns = pstSnsState;

    s32Ret  = CAMERA_InitSensorExpFunction(&stSns.stSnsAttrInfo.stSnsExp);
    s32Ret |= VISS_SensorRegCallBack(dev, &stSns);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor register callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = CAMERA_OpenI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterVissCallback(VISS_DEV dev)
{
    EI_S32 s32Ret;
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);

    s32Ret = CAMERA_ExitI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    s32Ret = VISS_SensorUnRegCallBack(dev, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor unregister callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    CAMERA_CtxExit(dev);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_RegisterIspCallback(VISS_DEV Dev, ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;
    AE_SENSOR_REGISTER_S  stAeRegister;
    AWB_SENSOR_REGISTER_S stAwbRegister;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    SNS_SET_ISP_TO_VISS(dev, Dev);

    stAeRegister.SnsId = SNS_ID;
    stAwbRegister.SnsId = SNS_ID;

    s32Ret  = CAMERA_InitAeExpFunction(&stAeRegister.stSnsExp);
    s32Ret |= EI_MI_AE_SensorRegCallBack(dev, pstAeLib, &stAeRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret  = CAMERA_InitAwbExpFunction(&stAwbRegister.stSnsExp);
    s32Ret |= EI_MI_AWB_SensorRegCallBack(dev, pstAwbLib, &stAwbRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterIspCallback(ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    s32Ret = EI_MI_AE_SensorUnRegCallBack(dev, pstAeLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = EI_MI_AWB_SensorUnRegCallBack(dev, pstAwbLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetVissDevAttrBySns(SNS_TYPE_E enType,
    VISS_DEV_ATTR_S *pstVissDevAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissDevAttr->stSize          = pstSnsType->stSize;
            pstVissDevAttr->enWorkMode      = pstSnsType->enWorkMode;
            pstVissDevAttr->mClock          = pstSnsType->u32Mclock;
            pstVissDevAttr->enPixelFormat   = pstSnsType->enPixelFormat;
            pstVissDevAttr->enWdrMode       = pstSnsType->enWdrMode;
            pstVissDevAttr->enIspWdrMode    = pstSnsType->enIspWdrMode;
            pstVissDevAttr->enRgbSeq        = pstSnsType->enRgbSeq;
            pstVissDevAttr->u32ModuleClk    = pstSnsType->u32ModuleClk;
            pstVissDevAttr->u32Fps          = pstSnsType->u32FrameRate;
            pstVissDevAttr->u32IspClk       = pstSnsType->u32IspClk;
            pstVissDevAttr->u32IppuClk      = pstSnsType->u32IppuClk;
            pstVissDevAttr->pcSnsName       = SNS_NAME;
            pstVissDevAttr->stDevCfg        = pstSnsType->stDevCfg;
            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this dev configuration", SNS_NAME);

    return EI_FAILURE;
}

static EI_S32 CAMERA_GetVissChnAttrBySns(SNS_TYPE_E enType,
    VISS_CHN_ATTR_S *pstVissChnAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissChnAttr->stSize           = pstSnsType->stSize;
            pstVissChnAttr->enPixelFormat    = pstSnsType->enPixelFormat;
            pstVissChnAttr->stFrameRate.s32SrcFrameRate      = pstSnsType->u32FrameRate;
            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);

    return EI_FAILURE;

}

CAMERA_OBJ_S stCameraGc4663mipiObj = {
    .pfnRegisterVissCallback    = CAMERA_RegisterVissCallback,
    .pfnUnRegisterVissCallback  = CAMERA_UnregisterVissCallback,
    .pfnRegisterIspCallback     = CAMERA_RegisterIspCallback,
    .pfnUnRegisterIspCallback   = CAMERA_UnregisterIspCallback,
    .pfnGetVissDevAttrBySns     = CAMERA_GetVissDevAttrBySns,
    .pfnGetVissChnAttrBySns     = CAMERA_GetVissChnAttrBySns,
};


#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

